﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Drawing;

namespace KXmlUIControl
{
    public class XmlWriteConfig
    {
        private string _file = "";
        private WindowType _windowType = WindowType.PageUserControl;
        private XmlDocument _xmlDoc = null;
        private XmlNode _root = null;
        private XmlFormObject _formObj = new XmlFormObject();
        private XmlCountdownObject _countdownObj = new XmlCountdownObject();
        private List<XmlButtonObject> _listButtons = new List<XmlButtonObject>();
        private List<XmlButtonObject> _listBaseButtons = new List<XmlButtonObject>();
        private List<XmlLabelObject> _listLabels = new List<XmlLabelObject>();
        private List<XmlTextBoxObject> _listTextBoxs = new List<XmlTextBoxObject>();
        private List<XmlPictureBoxObject> _listPicBoxs = new List<XmlPictureBoxObject>();
        public List<XmlPanelObject> _listPanels = new List<XmlPanelObject>();
        private List<XmlKCheckBoxObject> _listCheckBoxs = new List<XmlKCheckBoxObject>(); 
    
        private CodeParser _parser = null;

        public XmlWriteConfig(CodeParser parser, string file)
        {
            _parser = parser;
            _file = file; 
        }

        public XmlWriteConfig(XmlConfigForm config)
        {
            _formObj = config.FormConfig;
            _countdownObj = config.CountdownConfig;
            _listBaseButtons = config.ListBaseButtons;
            _listButtons = config.ListButtons;
            _listLabels = config.ListLabels;
            _listPicBoxs = config.ListPicBoxs;
            _listTextBoxs = config.ListTextBoxs;
            _listPanels = config.ListPanels;
            _listCheckBoxs = config.ListCheckBoxs;            
            _windowType = config.FormType;
           
        }

        private void InitCountDownObject()
        {
            _countdownObj.Name = "countdownControl1";
            _countdownObj.CountDownSecond = 60;
            _countdownObj.BackColor = "Transparent";
            _countdownObj.Enabled = false;
            _countdownObj.Visible = false;
            _countdownObj.Location = "1152, 0";
            _countdownObj.Size = "126, 72";
        }

        private void InitBaseButtons()
        {
            XmlButtonObject buttonNext = new XmlButtonObject();
            buttonNext.Name = "buttonNext";
            buttonNext.Click = "btnNext_Click";
            buttonNext.Location = "950, 730";
            buttonNext.Size = "150, 54";
            buttonNext.BackgroundImage = "下一步.jpg";

            XmlButtonObject buttonBack = new XmlButtonObject();
            buttonBack.Name = "buttonBack";
            buttonBack.Click = "btnBack_Click";
            buttonBack.Location = "550, 730";
            buttonBack.Size = "150, 54";
            buttonBack.BackgroundImage = "上一步.jpg";

            XmlButtonObject buttonCancel = new XmlButtonObject();
            buttonCancel.Name = "buttonCancel";
            buttonCancel.Click = "btnHome_Click";
            buttonCancel.Location = "150, 730";
            buttonCancel.Size = "150, 54";
            buttonCancel.BackgroundImage = "取消.jpg";

            _listBaseButtons.Add(buttonNext);
            _listBaseButtons.Add(buttonBack);
            _listBaseButtons.Add(buttonCancel);
        }

        private void OnPrepared()
        {
            _formObj = _parser.ParseForms();
            _listButtons = _parser.ParseButtons();          
            _listLabels = _parser.ParseLabels();
            _listPicBoxs = _parser.ParsePictureBoxs();
            _listTextBoxs = _parser.ParseTextBoxs();
            _listPanels = _parser.ParsePanels();
            _listCheckBoxs = _parser.ParseCheckBoxs();
            InitBaseButtons();
            InitCountDownObject();
        }

        public bool CreatXmlHeader()
        {
            if (File.Exists(_file))
            {
                File.Delete(_file);
            }
            try
            {
                _xmlDoc = new XmlDocument();
                XmlDeclaration xmlDec = _xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
                _xmlDoc.AppendChild(xmlDec);
                XmlElement newElem = _xmlDoc.CreateElement("Windows");
                newElem.SetAttribute("Type", _windowType.ToString());
                _xmlDoc.AppendChild(newElem);
                _root = _xmlDoc.SelectSingleNode("Windows");
                Func<string, string, XmlNode> insertChildNode = (name, comment) =>
                {
                    XmlElement childElem = _xmlDoc.CreateElement(name);
                    XmlNode node = _root.AppendChild(childElem);
                    // 添加注释
                    XmlComment commentNode = _xmlDoc.CreateComment(comment);
                    node.ParentNode.InsertBefore(commentNode, node);
                    return node;
                };
                if (_windowType == WindowType.MainForm)
                {
                    insertChildNode("Programs", "所有应用程序");
                }
                else if (_windowType == WindowType.ModuleApp)
                {
                    insertChildNode("Modules", "模块应用程序");
                }
                insertChildNode("Form", "主窗口样式");
                insertChildNode("ChildForm", "子窗口样式");
                insertChildNode("CountdownControl", "倒计时");
                insertChildNode("PictureBoxs", "图形显示控件");
                insertChildNode("TextBoxs", "文本编辑框");
                insertChildNode("Buttons", "按钮");
                insertChildNode("Labels", "文本标签控件");
                insertChildNode("Panels", "面板容器");
                insertChildNode("CheckBoxs", "复选框");
                if (_windowType == WindowType.PageUserControl)
                {
                    insertChildNode("BaseButtons", "流程控制按钮");
                }
                insertChildNode("Images", "从本地加载的图形对象");
                //XmlElement rowElem = xmlDoc.CreateElement("row");
                //DataRow row = dt.Rows[i];
                //for (int j = 0; j < dt.Columns.Count; j++)
                //{
                //    XmlElement colElem = xmlDoc.CreateElement("column");
                //    colElem.SetAttribute("name", dt.Columns[j].ColumnName);
                //    colElem.SetAttribute("value", row[j].ToString());
                //    rowElem.AppendChild(colElem);
                //}
                //valueElem.AppendChild(rowElem);
                //_xmlDoc.Save(_file);
            }
            catch
            {
                return false;
            }
            return true;
        }

        private bool AddXmlObject<T>(string nodeName, T t) where T : new()
        {
            try
            {                          
                XmlElement elem = _root[nodeName];
                SetXmlElementValue(elem, t);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private void SetXmlElementValue<T>(XmlElement elem, T t) where T : new()
        {
            Type type = typeof(T);
            PropertyInfo[] Properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (PropertyInfo p in Properties)
            {
                string name = p.Name;
                object oVal = p.GetValue(t, null);
                if (oVal == null)
                {
                    elem.SetAttribute(name, "");
                    continue;
                }
                string value = oVal.ToString();
                if (p.PropertyType == typeof(Color))
                {
                    value = ToColorString((Color)oVal);
                }
                if (!string.IsNullOrEmpty(value))
                {
                    elem.SetAttribute(name, value);
                }
                else
                {
                    elem.SetAttribute(name, "");
                }
            }
        }

        private bool AddXmlObject<T>(string parentName, string nodeName, T t) where T : new()
        {
            try
            {                        
                XmlElement parent = _root[parentName];
                XmlElement elem = _xmlDoc.CreateElement(nodeName);
                SetXmlElementValue(elem, t);
                parent.AppendChild(elem);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool AddXmlObjects<T>(string parentName, string nodeName, List<T> list) where T : new()
        {
            try
            {                        
                XmlElement parent = _root[parentName];
                Type type = typeof(T);
                for (int i = 0; i < list.Count; i++)
                {
                    XmlElement elem = _xmlDoc.CreateElement(nodeName);
                    SetXmlElementValue(elem, list[i]);
                    parent.AppendChild(elem);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Write(string file)
        {
            if (CreatXmlHeader())
            {
                AddXmlObject<XmlFormObject>("Form", _formObj);
                AddXmlObject<XmlCountdownObject>("CountdownControl", _countdownObj);
                AddXmlObjects<XmlButtonObject>("BaseButtons", "Button", _listBaseButtons);
                AddXmlObjects<XmlButtonObject>("Buttons", "Button", _listButtons);
                AddXmlObjects<XmlLabelObject>("Labels", "Label", _listLabels);
                AddXmlObjects<XmlPictureBoxObject>("PictureBoxs", "PictureBox", _listPicBoxs);
                AddXmlObjects<XmlTextBoxObject>("TextBoxs", "TextBox", _listTextBoxs);
                AddXmlObjects<XmlPanelObject>("Panels", "Panel", _listPanels);
                AddXmlObjects<XmlKCheckBoxObject>("CheckBoxs", "CheckBox", _listCheckBoxs);
                _xmlDoc.Save(file);
                return true;
            }
            return false;
        }

        public bool Write()
        {
            if (_parser != null)
            {
                OnPrepared();             
            }
            return Write(_file);
        }

        private static string ToColorString(Color color)
        {
            if (color.IsKnownColor || color.IsNamedColor || color.IsSystemColor)
            {
                return color.Name;
            }
            string strCol = color.ToString();
            int start = strCol.IndexOf('[');
            int end = strCol.IndexOf(']');
            string valueStr = strCol.Substring(start + 1, end - start - 1);
            string[] values = valueStr.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
            Dictionary<string, string> dic = new Dictionary<string, string>();
            foreach (string colVal in values)
            {
                string[] array = colVal.Split(new char[] { ' ', '=' }, StringSplitOptions.RemoveEmptyEntries);
                dic.Add(array[0], array[1]);
            }
            string msg = "";
            if (values.Length == 3)
            {
                msg = string.Format("({0}, {1}, {2})", dic["R"], dic["G"], dic["B"]);
            }
            if (values.Length == 4)
            {
                msg = string.Format("({0}, {1}, {2}, {3})", dic["A"], dic["R"], dic["G"], dic["B"]);
            }
            return msg;
        }

    }
}
